/*
 * Copyright (c) 2021 Talkweb Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "nfc.h"
#include <string.h>

/**
 * @brief 写NFC标签函数
 * @param param 待写入的NFC标签信息
 * @param tagCnt 待写入的NFC标签个数
 * @return 返回TRUE表示写入NFC标签成功
 */
BOOL NfcTagWrite(NdefFrame *param, unsigned char tagCnt)
{
    if (param == NULL)
    {
        printf("NfcTagWrite() param err!\r\n");
        return FALSE;
    }

    if (tagCnt <= 0)
    {
        printf("NfcTagWrite() tagCnt <= 0!\r\n");
        return FALSE;
    }

    MemFrame *memFrame = (MemFrame *)malloc(sizeof(MemFrame) * tagCnt);
    if (memFrame == NULL)
    {
        printf("NfcTagWrite() malloc err!\r\n");
        return FALSE;
    }
    memset(memFrame, 0, sizeof(MemFrame) * tagCnt);

    // 获取TLV协议格式中的消息长度
    unsigned short tlvLen = 0;
    for (unsigned int i = 0; i < tagCnt; i++)
    {
        if (NdefPackMake(&param[i], &memFrame[i]) != TRUE)
        {
            printf("NdefPackMake() tagCnt[%u] err!\r\n", i);
            free(memFrame);
            return FALSE;
        }
        tlvLen += memFrame[i].len;
    }

    unsigned int nfcStartAddr = 0;
    MemFrame tlvHeadBuf = {0};
    tlvHeadBuf.data[0] = NFC_TLV_HEAD;
    if (tlvLen > 255)
    {
        tlvHeadBuf.data[1] = 0xff;
        tlvHeadBuf.data[2] = (unsigned char)(tlvLen >> 8) & 0xff;
        tlvHeadBuf.data[3] = (unsigned char)(tlvLen >> 0) & 0xff;
        tlvHeadBuf.len = 4;
        nfcStartAddr = NFC_EEPROM_ADDR_START + 4;
    }
    else
    {
        tlvHeadBuf.data[1] = tlvLen;
        tlvHeadBuf.len = 2;
        nfcStartAddr = NFC_EEPROM_ADDR_START + 2;
    }

    if (NfcI2CWriteMem(NFC_EEPROM_ADDR_START, &tlvHeadBuf) != TRUE)
    {
        printf("NfcI2CWriteMem() tlvHeadBuf err!\r\n");
        free(memFrame);
        return FALSE;
    }

    for (unsigned int i = 0; i < tagCnt; i++)
    {
        if (NfcI2CWriteMem(nfcStartAddr, &memFrame[i]) != TRUE)
        {
            printf("NfcI2CWriteMem() tagCnt[%u] err!\r\n", i);
            free(memFrame);
            return FALSE;
        }
        nfcStartAddr += memFrame[i].len;
    }

    free(memFrame);
    return TRUE;
}

/**
 * @brief 读NFC标签函数
 * @return 返回读取到的NFC标签链表头
 */
NdefParsingList *NfcTagRead(void)
{
    unsigned char *memBuf = (unsigned char *)malloc(NFC_EEPROM_SIZE);
    if (memBuf == NULL)
    {
        printf("NfcTagRead() malloc err!\r\n");
        return NULL;
    }
    memset(memBuf, 0, NFC_EEPROM_SIZE);

    NfcI2CReadMem(NFC_EEPROM_ADDR_START, NFC_EEPROM_SIZE, memBuf);

    if (memBuf[0] != NFC_TLV_HEAD)
    {
        printf("NfcTagRead() err: memBuf[0] != %02x \r\n", NFC_TLV_HEAD);
        free(memBuf);
        return NULL;
    }

    unsigned int memLen = 0;
    unsigned int startAddr = 0;
    if (memBuf[1] == 0xff)
    {
        memLen = (memBuf[2] << 8) | memBuf[3];
        startAddr = 4;
    }
    else
    {
        memLen = memBuf[1];
        startAddr = 2;
    }

    if (memLen > (NFC_EEPROM_SIZE - startAddr))
    {
        printf("NfcTagRead() err: tlv memLen overflow, memLen = %u\r\n", memLen);
        free(memBuf);
        return NULL;
    }

    NdefParsingList *head, *node, *end;
    end = head = (NdefParsingList *)malloc(sizeof(NdefParsingList));
    while (startAddr <= memLen)
    {
        node = (NdefParsingList *)malloc(sizeof(NdefParsingList));
        end->next = node;
        node->next = NULL;
        end = node;

        if (NdefPackParsing(&node->ndef, &memBuf[startAddr]) != TRUE)
        {
            printf("NdefPackParsing() err\r\n");
            free(memBuf);
            NfcReadTagFree(head);
            return NULL;
        }
        startAddr += (node->ndef.payloadLen + 4);
        startAddr += (node->ndef.dataType == RTD_UTF8) ? 3 : 1;
    }

    free(memBuf);
    return (NdefParsingList*)head;
}

/**
 * @brief 读NFC标签释放函数
 * @param list 待释放的NFC标签链表头
 */
void NfcReadTagFree(NdefParsingList *list)
{
    NdefParsingList *p = list, *pr = NULL;

    while (p != NULL)
    {
        pr = p;
        p = p->next;
        free(pr);
    }
}
